package thoven.achievement.net.ideapluginachievement.service

import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.components.service
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.wm.WindowManager
import com.intellij.util.messages.Topic
import com.intellij.util.xmlb.annotations.OptionTag
import thoven.achievement.net.ideapluginachievement.model.Achievement
import thoven.achievement.net.ideapluginachievement.model.AchievementType
import thoven.achievement.net.ideapluginachievement.model.AggregatedCodeStats
import thoven.achievement.net.ideapluginachievement.model.AchievementProgress
import thoven.achievement.net.ideapluginachievement.model.CodeStats
import thoven.achievement.net.ideapluginachievement.util.LanguageDetector
import thoven.achievement.net.ideapluginachievement.util.LocalDateConverter
import thoven.achievement.net.ideapluginachievement.util.LocalDateTimeConverter
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.DayOfWeek
import java.io.Serializable
import java.util.EventListener

/**
 * 代码统计更新监听器
 */
interface CodeStatsListener : EventListener {
    fun onStatsChanged()
    
    companion object {
        val TOPIC = Topic.create("CodeStatsChanged", CodeStatsListener::class.java)
    }
}

/**
 * 代码统计服务，用于跟踪和存储代码行数
 */
@Service(Service.Level.PROJECT)
@State(
    name = "CodeStatsService",
    storages = [Storage("code-stats.xml")]
)
class CodeStatsService(private val project: Project) : PersistentStateComponent<CodeStatsService.State> {
    
    private val LOG = logger<CodeStatsService>()
    
    /**
     * 持久化状态类
     */
    class State : Serializable {
        var codeStats: MutableList<CodeStats> = mutableListOf()
        var achievements: MutableList<Achievement> = mutableListOf()
        var consecutiveDays: Int = 0
        
        @OptionTag(converter = LocalDateConverter::class)
        var lastActiveDate: LocalDate? = null
        
        var saveCount: Int = 0
        var pasteCount: Int = 0
        var ideaRestartCount: Int = 0
        var todoFixmeCount: Int = 0
        var consoleLogCount: Int = 0
        
        @OptionTag(converter = LocalDateTimeConverter::class)
        var firstCodeTimeToday: LocalDateTime? = null
        
        @OptionTag(converter = LocalDateTimeConverter::class)
        var lastCodeTimeToday: LocalDateTime? = null
        
        // 注意：列表类型不能直接使用转换器，需要特殊处理
        // 暂时改为使用字符串列表存储，在使用时转换
        var codingStartTimesStr: MutableList<String> = mutableListOf()
        
        var largestSingleDelete: Int = 0
        
        // 网络热梗成就相关统计
        var compilationErrors: Int = 0
        var windowSwitchCount: Int = 0
        var socialDeathComments: Int = 0
        var emergencyFixCount: Int = 0
        var maxFileLines: Int = 0
        var complexPatternCount: Int = 0
        
        // 添加一个无参构造函数，用于序列化
        constructor()
        
        // 添加一个拷贝构造函数
        constructor(other: State) {
            this.codeStats = other.codeStats.toMutableList()
            this.achievements = other.achievements.toMutableList()
            this.consecutiveDays = other.consecutiveDays
            this.lastActiveDate = other.lastActiveDate
            this.saveCount = other.saveCount
            this.pasteCount = other.pasteCount
            this.ideaRestartCount = other.ideaRestartCount
            this.todoFixmeCount = other.todoFixmeCount
            this.consoleLogCount = other.consoleLogCount
            this.firstCodeTimeToday = other.firstCodeTimeToday
            this.lastCodeTimeToday = other.lastCodeTimeToday
            this.codingStartTimesStr = other.codingStartTimesStr.toMutableList()
            this.largestSingleDelete = other.largestSingleDelete
            this.compilationErrors = other.compilationErrors
            this.windowSwitchCount = other.windowSwitchCount
            this.socialDeathComments = other.socialDeathComments
            this.emergencyFixCount = other.emergencyFixCount
            this.maxFileLines = other.maxFileLines
            this.complexPatternCount = other.complexPatternCount
        }
        
        // 辅助方法：获取 LocalDateTime 列表
        fun getCodingStartTimes(): MutableList<LocalDateTime> {
            return codingStartTimesStr.mapNotNull {
                try {
                    LocalDateTime.parse(it)
                } catch (e: Exception) {
                    null
                }
            }.toMutableList()
        }
        
        // 辅助方法：设置 LocalDateTime 列表
        fun setCodingStartTimes(times: List<LocalDateTime>) {
            codingStartTimesStr = times.map { it.toString() }.toMutableList()
        }
    }
    
    private var myState = State()
    
    init {
        // 初始化时检查连续天数
        checkConsecutiveDays()
    }
    
    /**
     * 获取今天的代码统计
     */
    fun getTodayStats(): List<CodeStats> {
        val today = LocalDate.now()
        return getStatsByDate(today)
    }
    
    /**
     * 获取指定日期的代码统计
     */
    fun getStatsByDate(date: LocalDate): List<CodeStats> {
        return myState.codeStats.filter { it.date == date }
    }
    
    /**
     * 获取指定日期范围的代码统计
     */
    fun getStatsByDateRange(startDate: LocalDate, endDate: LocalDate): List<CodeStats> {
        return myState.codeStats.filter { 
            (it.date.isEqual(startDate) || it.date.isAfter(startDate)) && 
            (it.date.isEqual(endDate) || it.date.isBefore(endDate)) 
        }
    }
    
    /**
     * 获取指定日期的成就
     */
    fun getAchievementsByDate(date: LocalDate): List<Achievement> {
        return myState.achievements.filter { it.date == date && it.unlocked }
    }
    
    /**
     * 获取指定日期范围的成就
     */
    fun getAchievementsByDateRange(startDate: LocalDate, endDate: LocalDate): List<Achievement> {
        return myState.achievements.filter { 
            it.unlocked && 
            (it.date.isEqual(startDate) || it.date.isAfter(startDate)) && 
            (it.date.isEqual(endDate) || it.date.isBefore(endDate)) 
        }
    }
    
    /**
     * 获取累计的代码统计
     */
    fun getAggregatedStats(): AggregatedCodeStats {
        val today = LocalDate.now()
        val todayStats = getStatsByDate(today)
        val todayAdded = todayStats.sumOf { it.addedLines }
        val todayDeleted = todayStats.sumOf { it.deletedLines }
        
        val totalAdded = myState.codeStats.sumOf { it.addedLines }
        val totalDeleted = myState.codeStats.sumOf { it.deletedLines }
        val totalNet = totalAdded - totalDeleted
        
        return AggregatedCodeStats(
            todayAdded = todayAdded,
            todayDeleted = todayDeleted,
            totalAdded = totalAdded,
            totalDeleted = totalDeleted,
            totalNet = totalNet
        )
    }
    
    /**
     * 记录代码变更
     */
    fun recordCodeChange(file: VirtualFile, addedLines: Int, deletedLines: Int) {
        if (!LanguageDetector.isCodeFile(file) || (addedLines == 0 && deletedLines == 0)) {
            return
        }
        
        val language = LanguageDetector.detectLanguage(file)
        val today = LocalDate.now()
        val now = LocalDateTime.now()
        
        // 记录第一次和最后一次编码时间
        if (myState.firstCodeTimeToday == null || !myState.firstCodeTimeToday!!.toLocalDate().equals(today)) {
            myState.firstCodeTimeToday = now
        }
        myState.lastCodeTimeToday = now
        
        // 查找或创建今天对应语言的统计记录
        val stats = myState.codeStats.find { it.date == today && it.language == language }
            ?: CodeStats(date = today, language = language).also {
                myState.codeStats.add(it)
            }
        
        // 更新统计数据
        stats.addedLines += addedLines
        stats.deletedLines += deletedLines
        
        // 更新最大单次删除行数
        if (deletedLines > myState.largestSingleDelete) {
            myState.largestSingleDelete = deletedLines
        }
        
        // 检查成就
        checkAchievements()
        
        // 通知状态栏更新
        notifyStatsChanged()
    }
    
    /**
     * 记录保存操作
     */
    fun recordSave() {
        myState.saveCount++
        checkAchievements()
    }
    
    /**
     * 记录粘贴操作
     */
    fun recordPaste() {
        myState.pasteCount++
        checkAchievements()
    }
    
    /**
     * 记录IDEA重启
     */
    fun recordIdeaRestart() {
        myState.ideaRestartCount++
        checkAchievements()
    }
    
    /**
     * 记录TODO/FIXME注释
     */
    fun recordTodoFixme() {
        myState.todoFixmeCount++
        checkAchievements()
    }
    
    /**
     * 记录console.log
     */
    fun recordConsoleLog() {
        myState.consoleLogCount++
        checkAchievements()
    }
    
    /**
     * 记录编译错误
     */
    fun recordCompilationError() {
        myState.compilationErrors++
        checkAchievements()
    }
    
    /**
     * 记录窗口切换
     */
    fun recordWindowSwitch() {
        myState.windowSwitchCount++
        checkAchievements()
    }
    
    /**
     * 记录社死注释
     */
    fun recordSocialDeathComment() {
        myState.socialDeathComments++
        checkAchievements()
    }
    
    /**
     * 记录紧急修复
     */
    fun recordEmergencyFix() {
        myState.emergencyFixCount++
        checkAchievements()
    }
    
    /**
     * 记录文件最大行数
     */
    fun recordMaxFileLines(lines: Int) {
        if (lines > myState.maxFileLines) {
            myState.maxFileLines = lines
        }
        checkAchievements()
    }
    
    /**
     * 记录复杂模式
     */
    fun recordComplexPattern() {
        myState.complexPatternCount++
        checkAchievements()
    }
    
    /**
     * 重置每日计数器
     * 在项目启动时调用，如果日期已变更则重置计数器
     */
    fun resetDailyCounters() {
        val today = LocalDate.now()
        val lastActive = myState.lastActiveDate
        
        // 如果不是同一天，重置每日计数器
        if (lastActive == null || !lastActive.equals(today)) {
            myState.saveCount = 0
            myState.pasteCount = 0
            myState.ideaRestartCount = 0
            myState.todoFixmeCount = 0
            myState.consoleLogCount = 0
            myState.compilationErrors = 0
            myState.windowSwitchCount = 0
            myState.socialDeathComments = 0
            myState.emergencyFixCount = 0
            myState.complexPatternCount = 0
            myState.firstCodeTimeToday = null
            myState.lastCodeTimeToday = null
            
            // 清空编码开始时间列表
            myState.codingStartTimesStr.clear()
            
            LOG.info("每日计数器已重置")
        }
    }
    
    /**
     * 检查连续天数
     */
    private fun checkConsecutiveDays() {
        val today = LocalDate.now()
        val lastActive = myState.lastActiveDate
        
        if (lastActive == null) {
            // 首次使用
            myState.consecutiveDays = 1
            myState.lastActiveDate = today
            unlockAchievement(AchievementType.SIGN_IN_DAY1)
        } else if (lastActive.equals(today)) {
            // 今天已经记录过了，不做任何操作
        } else if (lastActive.plusDays(1).equals(today)) {
            // 连续天数+1
            myState.consecutiveDays++
            myState.lastActiveDate = today
            
            // 检查连续天数成就
            if (myState.consecutiveDays >= 100) {
                unlockAchievement(AchievementType.DREAM_100_DAYS)
            } else if (myState.consecutiveDays >= 30) {
                unlockAchievement(AchievementType.IRON_30_DAYS)
            } else if (myState.consecutiveDays >= 7) {
                unlockAchievement(AchievementType.CRAZY_7_DAYS)
            } else if (myState.consecutiveDays >= 1) {
                unlockAchievement(AchievementType.SIGN_IN_DAY1)
            }
        } else if (lastActive.isBefore(today)) {
            // 中断了连续天数
            myState.consecutiveDays = 1
            myState.lastActiveDate = today
            unlockAchievement(AchievementType.SIGN_IN_DAY1)
        }
    }
    
    /**
     * 通知代码统计已更改
     */
    fun notifyStatsChanged() {
        project.messageBus.syncPublisher(CodeStatsListener.TOPIC).onStatsChanged()
        
        // 强制刷新状态栏
        WindowManager.getInstance()?.getStatusBar(project)?.updateWidget("CodeStatsWidget")
    }
    
    /**
     * 检查成就
     */
    private fun checkAchievements() {
        val today = LocalDate.now()
        val todayStats = getTodayStats()
        val todayAdded = todayStats.sumOf { it.addedLines }
        val todayDeleted = todayStats.sumOf { it.deletedLines }
        val totalStats = getAggregatedStats()
        val now = LocalDateTime.now()
        
        // 检查按行数的成就
        if (todayAdded >= 1000) {
            unlockAchievement(AchievementType.LEGENDARY_1000)
        } else if (todayAdded >= 500) {
            unlockAchievement(AchievementType.HARD_WORKER)
        } else if (todayAdded >= 300) {
            unlockAchievement(AchievementType.KEYBOARD_FLYING)
        } else if (todayAdded >= 100) {
            unlockAchievement(AchievementType.WARM_UP)
        }
        
        // 检查累计行数成就
        if (totalStats.totalAdded >= 10000) {
            unlockAchievement(AchievementType.CODE_MACHINE)
        }
        
        // 检查按删除的成就
        if (todayDeleted >= 200) {
            unlockAchievement(AchievementType.DELETE_DB)
        }
        
        // 检查累计删除行数成就
        if (totalStats.totalDeleted >= 5000) {
            unlockAchievement(AchievementType.REFACTOR_MASTER)
        }
        
        // 检查单次大量删除成就
        if (myState.largestSingleDelete >= 1000) {
            unlockAchievement(AchievementType.DELETE_AND_RUN)
        }
        
        // 检查时间相关成就
        val firstCodeTime = myState.firstCodeTimeToday
        if (firstCodeTime != null && firstCodeTime.toLocalDate().equals(today)) {
            // 早起的程序猿
            if (firstCodeTime.toLocalTime().isBefore(LocalTime.of(9, 0))) {
                unlockAchievement(AchievementType.EARLY_BIRD)
            }
        }
        
        val lastCodeTime = myState.lastCodeTimeToday
        if (lastCodeTime != null && lastCodeTime.toLocalDate().equals(today)) {
            // 深夜键仙
            if (lastCodeTime.toLocalTime().isAfter(LocalTime.of(1, 0)) && 
                lastCodeTime.toLocalTime().isBefore(LocalTime.of(5, 0))) {
                unlockAchievement(AchievementType.NIGHT_CODER)
            }
        }
        
        // 检查周末爆肝王
        if (today.dayOfWeek == DayOfWeek.SATURDAY || today.dayOfWeek == DayOfWeek.SUNDAY) {
            if (todayAdded >= 300) {
                unlockAchievement(AchievementType.WEEKEND_WARRIOR)
            }
        }
        
        // 检查趣味彩蛋成就
        if (myState.todoFixmeCount >= 5) {
            unlockAchievement(AchievementType.BUG_HARVESTER)
        }
        
        if (myState.saveCount >= 200) {
            unlockAchievement(AchievementType.CTRL_S_BELIEVER)
        }
        
        if (myState.pasteCount >= 100) {
            unlockAchievement(AchievementType.COPY_PASTE_MASTER)
        }
        
        if (myState.ideaRestartCount >= 5) {
            unlockAchievement(AchievementType.IDEA_RESTARTER)
        }
        
        if (myState.consoleLogCount >= 50) {
            unlockAchievement(AchievementType.CONSOLE_LOG_PRIEST)
        }
        
        // 检查网络热梗成就
        checkInternetMemeAchievements(today, todayStats, todayAdded, todayDeleted, now)
    }
    
    /**
     * 解锁成就
     */
    private fun unlockAchievement(type: AchievementType) {
        val today = LocalDate.now()
        
        // 检查今天是否已经解锁了该成就
        val existingAchievement = myState.achievements.find { 
            it.type == type && it.date == today 
        }
        
        if (existingAchievement == null) {
            // 记录解锁时间戳（用于NEW标签显示）
            val achievement = Achievement(
                type = type, 
                date = today, 
                unlocked = true,
                unlockTimestamp = System.currentTimeMillis()
            )
            myState.achievements.add(achievement)
            
            // 显示成就解锁通知
            val notificationService = AchievementNotificationService.getInstance(project)
            notificationService.showAchievementUnlockedNotification(achievement)
            
            // 通知状态栏更新
            notifyStatsChanged()
        }
    }
    
    /**
     * 检查网络热梗成就
     */
    private fun checkInternetMemeAchievements(
        today: LocalDate, 
        todayStats: List<CodeStats>, 
        todayAdded: Int, 
        todayDeleted: Int, 
        now: LocalDateTime
    ) {
        // 1. 绝绝子：一天内解锁3个以上成就
        val todayAchievements = myState.achievements.filter { it.date == today }
        if (todayAchievements.size >= 3) {
            unlockAchievement(AchievementType.ABSOLUTELY_AMAZING)
        }
        
        // 2. 艺术就是爆炸：一次性删除500行以上代码
        if (myState.largestSingleDelete >= 500) {
            unlockAchievement(AchievementType.ART_IS_EXPLOSION)
        }
        
        // 3. YYDS永远的神：连续30天每天都有代码提交
        if (myState.consecutiveDays >= 30) {
            unlockAchievement(AchievementType.YYDS_FOREVER)
        }
        
        // 4. 纯纯大怨种：深夜加班写代码到凌晨3点
        if (now.toLocalTime().isAfter(LocalTime.of(3, 0)) && 
            now.toLocalTime().isBefore(LocalTime.of(5, 0)) && 
            todayAdded > 0) {
            unlockAchievement(AchievementType.PURE_GRUDGE_HOLDER)
        }
        
        // 5. 躺平：一周内代码量少于10行
        val weeklyStats = getStatsForPastDays(7)
        val weeklyTotal = weeklyStats.sumOf { it.addedLines }
        if (weeklyTotal < 10) {
            unlockAchievement(AchievementType.LYING_FLAT)
        }
        
        // 6. 内卷之王：周末写代码超过工作日
        checkInvolutionKing(today, todayAdded)
        
        // 7. 又不是不能用：写出勉强能跑的代码（基于TODO/FIXME密度）
        if (myState.todoFixmeCount >= 3 && todayAdded >= 100) {
            unlockAchievement(AchievementType.NOT_UNUSABLE)
        }
        
        // 8. 社死：在代码注释中写了奇怪的内容（基于特殊关键词检测）
        if (myState.socialDeathComments >= 1) {
            unlockAchievement(AchievementType.SOCIAL_DEATH)
        }
        
        // 9. 细思极恐：写出复杂度过高的代码（基于单文件行数）
        if (myState.maxFileLines >= 1000) {
            unlockAchievement(AchievementType.TERRIFYING_WHEN_THINK)
        }
        
        // 10. 麻了：连续遇到5个以上编译错误
        if (myState.compilationErrors >= 5) {
            unlockAchievement(AchievementType.PARALYZED)
        }
        
        // 11. 蚌埠住了：写出让人无语的代码（基于特殊模式检测）
        if (myState.complexPatternCount >= 3) {
            unlockAchievement(AchievementType.CANT_HOLD_IT)
        }
        
        // 12. 鸡你太美：频繁切换窗口编写代码
        if (myState.windowSwitchCount >= 50 && todayAdded >= 100) {
            unlockAchievement(AchievementType.CHICKEN_YOU_ARE_TOO_BEAUTIFUL)
        }
        
        // 13. 有内鬼，终止交易：发现严重bug后紧急回滚
        checkInsiderAbortDeal(today)
        
        // 14. 破防了：自己的代码被别人大量重构（基于删除/修改比例）
        if (todayDeleted > todayAdded && todayDeleted >= 200) {
            unlockAchievement(AchievementType.DEFENSE_BROKEN)
        }
        
        // 15. 出什么事了：紧急修复线上bug（基于深夜紧急修复模式）
        if (myState.emergencyFixCount >= 1) {
            unlockAchievement(AchievementType.WHAT_HAPPENED)
        }
    }
    
    /**
     * 检查有内鬼，终止交易成就
     */
    private fun checkInsiderAbortDeal(today: LocalDate) {
        // 基于今天的删除代码量和时间模式判断是否为紧急回滚
        val todayStats = getTodayStats()
        val todayDeleted = todayStats.sumOf { it.deletedLines }
        val now = LocalDateTime.now()
        
        // 如果在非正常工作时间（晚上10点后或早上6点前）大量删除代码，可能是紧急回滚
        val isEmergencyTime = now.toLocalTime().isAfter(LocalTime.of(22, 0)) || 
                             now.toLocalTime().isBefore(LocalTime.of(6, 0))
        
        if (isEmergencyTime && todayDeleted >= 300) {
            unlockAchievement(AchievementType.HAVE_INSIDER_ABORT_DEAL)
        }
        
        // 或者基于短时间内大量删除判断
        if (myState.largestSingleDelete >= 800) {
            unlockAchievement(AchievementType.HAVE_INSIDER_ABORT_DEAL)
        }
    }
    
    /**
     * 检查内卷之王成就
     */
    private fun checkInvolutionKing(today: LocalDate, todayAdded: Int) {
        val dayOfWeek = today.dayOfWeek
        
        // 如果是周末且写了代码
        if ((dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY) && todayAdded > 0) {
            // 获取最近的工作日平均代码量
            val pastWeekStats = getStatsForPastDays(7)
            val workdayStats = pastWeekStats.filter { stat ->
                val statDay = stat.date.dayOfWeek
                statDay != DayOfWeek.SATURDAY && statDay != DayOfWeek.SUNDAY
            }
            
            if (workdayStats.isNotEmpty()) {
                val avgWorkdayLines = workdayStats.sumOf { it.addedLines } / workdayStats.size
                
                // 周末代码量超过工作日平均值
                if (todayAdded > avgWorkdayLines) {
                    unlockAchievement(AchievementType.INVOLUTION_KING)
                }
            }
        }
    }
    
    /**
     * 获取过去N天的统计数据
     */
    private fun getStatsForPastDays(days: Int): List<CodeStats> {
        val endDate = LocalDate.now()
        val startDate = endDate.minusDays(days.toLong())
        
        return myState.codeStats.filter { stat ->
            !stat.date.isBefore(startDate) && !stat.date.isAfter(endDate)
        }
    }
    
    /**
     * 获取已解锁的成就
     */
    fun getUnlockedAchievements(): List<Achievement> {
        return myState.achievements.filter { it.unlocked }
    }
    
    /**
     * 获取今天解锁的成就
     */
    fun getTodayAchievements(): List<Achievement> {
        val today = LocalDate.now()
        return getAchievementsByDate(today)
    }
    
    /**
     * 获取连续天数
     */
    fun getConsecutiveDays(): Int {
        return myState.consecutiveDays
    }
    
    /**
     * 计算指定成就的进度
     * @return AchievementProgress 或 null（如果成就类型不适用进度计算）
     */
    fun calculateAchievementProgress(type: AchievementType): AchievementProgress? {
        val today = LocalDate.now()
        val todayStats = getTodayStats()
        val todayAdded = todayStats.sumOf { it.addedLines }
        val todayDeleted = todayStats.sumOf { it.deletedLines }
        val totalStats = getAggregatedStats()
        
        // 检查该成就是否已解锁
        val isUnlocked = myState.achievements.any { it.type == type && it.unlocked }
        
        // 根据成就类型计算当前值和目标值
        val (currentValue, targetValue) = when (type) {
            // 按今日新增行数
            AchievementType.WARM_UP -> Pair(todayAdded, 100)
            AchievementType.KEYBOARD_FLYING -> Pair(todayAdded, 300)
            AchievementType.HARD_WORKER -> Pair(todayAdded, 500)
            AchievementType.LEGENDARY_1000 -> Pair(todayAdded, 1000)
            
            // 按累计新增行数
            AchievementType.CODE_MACHINE -> Pair(totalStats.totalAdded, 10000)
            
            // 按今日删除行数
            AchievementType.DELETE_DB -> Pair(todayDeleted, 200)
            
            // 按累计删除行数
            AchievementType.REFACTOR_MASTER -> Pair(totalStats.totalDeleted, 5000)
            
            // 按单次删除行数
            AchievementType.DELETE_AND_RUN -> Pair(myState.largestSingleDelete, 1000)
            
            // 按连续天数
            AchievementType.SIGN_IN_DAY1 -> Pair(myState.consecutiveDays, 1)
            AchievementType.CRAZY_7_DAYS -> Pair(myState.consecutiveDays, 7)
            AchievementType.IRON_30_DAYS -> Pair(myState.consecutiveDays, 30)
            AchievementType.DREAM_100_DAYS -> Pair(myState.consecutiveDays, 100)
            
            // 按趣味彩蛋计数
            AchievementType.BUG_HARVESTER -> Pair(myState.todoFixmeCount, 5)
            AchievementType.CTRL_S_BELIEVER -> Pair(myState.saveCount, 200)
            AchievementType.COPY_PASTE_MASTER -> Pair(myState.pasteCount, 100)
            AchievementType.IDEA_RESTARTER -> Pair(myState.ideaRestartCount, 5)
            AchievementType.CONSOLE_LOG_PRIEST -> Pair(myState.consoleLogCount, 50)
            
            // 时间相关成就不适用进度计算
            else -> return null
        }
        
        // 创建虚拟Achievement对象以获取名称和描述
        val dummyAchievement = Achievement(type = type, date = today, unlocked = false)
        val progressPercent = if (targetValue > 0) {
            ((currentValue.toDouble() / targetValue) * 100).toInt().coerceAtMost(100)
        } else {
            0
        }
        
        return AchievementProgress(
            type = type,
            name = dummyAchievement.getName(),
            description = dummyAchievement.getDescription(),
            icon = dummyAchievement.getIcon(),
            currentValue = currentValue,
            targetValue = targetValue,
            progressPercent = progressPercent,
            isUnlocked = isUnlocked
        )
    }
    
    /**
     * 获取所有成就的进度列表
     * 只返回适用进度计算的成就
     */
    fun getAllAchievementProgress(): List<AchievementProgress> {
        return AchievementType.values()
            .mapNotNull { calculateAchievementProgress(it) }
    }
    
    /**
     * 获取最接近解锁的未解锁成就（按进度排序，最多返回 N 个）
     */
    fun getClosestAchievements(limit: Int = 3): List<AchievementProgress> {
        return getAllAchievementProgress()
            .filter { !it.isUnlocked }
            .sortedByDescending { it.progressPercent }
            .take(limit)
    }
    
    
    override fun getState(): State {
        return State(myState) // 返回一个副本以避免修改原始状态
    }
    
    override fun loadState(state: State) {
        myState = State(state) // 创建一个副本以避免外部修改
    }
    
    companion object {
        fun getInstance(project: Project): CodeStatsService = project.service()
    }
} 